package com.hiking.cmdchat;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import com.hiking.cmdchat.adapter.MessageAdapter;
import com.hiking.cmdchat.bean.Message;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;

import static com.hiking.cmdchat.bean.Message.TYPE_MESSAGE;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    @BindView(R.id.recycle)
    RecyclerView mMessagesView;
    @BindView(R.id.edit)
    MyEditerView myEditerView;

    private RecyclerView.Adapter mAdapter;

    private List<Message> mMessages = new ArrayList<>();

    private Socket mSocket;
    private Boolean isConnected = true;

    private static final int REQUEST_LOGIN = 0;

    private static final int TYPING_TIMER_LENGTH = 600;
    private String mUsername;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        initSocket();
        initData();
        initRecycle();
        myEditerView.setOnSendListener(new MyEditerView.SendListener() {
            @Override
            public void onSendClick(String data) {
                sendData(data);
            }
        });
        mAdapter.notifyDataSetChanged();

    }


    private void sendData(String data) {
        if (null == mMessages || TextUtils.isEmpty(data)) return;
        if (data.equals("help")) {
            mMessages.add(new Message.Builder(TYPE_MESSAGE).username("<<").message("List of all MySQL commands:\n" +
                    "Note that all text commands must be first on line and end with ';'\n" +
                    "?         (\\?) Synonym for `help'.\n" +
                    "clear     (\\c) Clear the current input statement.\n" +
                    "connect   (\\r) Reconnect to the server. Optional arguments are db and host.\n" +
                    "delimiter (\\d) Set statement delimiter.\n" +
                    "ego       (\\G) Send command to mysql server, display result vertically.\n" +
                    "exit      (\\q) Exit mysql. Same as quit.\n" +
                    "go        (\\g) Send command to mysql server.\n" +
                    "help      (\\h) Display this help.\n" +
                    "notee     (\\t) Don't write into outfile.\n" +
                    "print     (\\p) Print current command.\n" +
                    "prompt    (\\R) Change your mysql prompt.\n" +
                    "quit      (\\q) Quit mysql.\n" +
                    "rehash    (\\#) Rebuild completion hash.\n" +
                    "source    (\\.) Execute an SQL script file. Takes a file name as an argument.\n" +
                    "status    (\\s) Get status information from the server.\n" +
                    "tee       (\\T) Set outfile [to_outfile]. Append everything into given outfile.\n" +
                    "tee       (\\T) Set outfile [to_outfile]. Append everything into given outfile.\n" +
                    "tee       (\\T) Set outfile [to_outfile]. Append everything into given outfile.\n" +
                    "tee       (\\T) Set outfile [to_outfile]. Append everything into given outfile.\n" +
                    "tee       (\\T) Set outfile [to_outfile]. Append everything into given outfile.\n" +
                    "tee       (\\T) Set outfile [to_outfile]. Append everything into given outfile.\n" +
                    "tee       (\\T) Set outfile [to_outfile]. Append everything into given outfile.\n" +
                    "tee       (\\T) Set outfile [to_outfile]. Append everything into given outfile.\n" +
                    "use       (\\u) Use another database. Takes database name as argument.\n" +
                    "charset   (\\C) Switch to another charset. Might be needed for processing binlog\n" +
                    "with multi-byte charsets.\n" +
                    "warnings  (\\W) Show warnings after every statement.\n" +
                    "nowarning (\\w) Don't show warnings after every statement.\n" +
                    "resetconnection(\\x) Clean session context.\n" +
                    "\n" +
                    "For server side help, type 'help contents'").build());
        } else if (data.equals("clear")) {
            mMessages.clear();
        } else {
            mMessages.add(new Message.Builder(TYPE_MESSAGE).username("<<").message(data).build());
        }
        mAdapter.notifyDataSetChanged();
        scrollToBottom();
    }

    private void scrollToBottom() {
        mMessagesView.scrollToPosition(mAdapter.getItemCount() - 1);
    }

    private void initData() {
        mAdapter = new MessageAdapter(this, mMessages);
    }


    private void initRecycle() {
        mMessagesView.setLayoutManager(new LinearLayoutManager(this));
        mMessagesView.setAdapter(mAdapter);

    }


    private void initSocket() {
        ChatApplication app = (ChatApplication) getApplication();
        mSocket = app.getSocket();
        mSocket.on(Socket.EVENT_CONNECT, onConnect);
        mSocket.on(Socket.EVENT_DISCONNECT, onDisconnect);
        mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectError);
        mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, onConnectError);
        mSocket.on("new message", onNewMessage);
        mSocket.on("user joined", onUserJoined);
//        mSocket.on("user left", onUserLeft);
//        mSocket.on("typing", onTyping);
//        mSocket.on("stop typing", onStopTyping);
        mSocket.connect();
//        startSignIn();
    }

//    private void startSignIn() {
//        mUsername = null;
//        Intent intent = new Intent(getActivity(), LoginActivity.class);
//        startActivityForResult(intent, REQUEST_LOGIN);
//    }

    private Emitter.Listener onConnect = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (!isConnected) {
                        if (null != mUsername)
                            mSocket.emit("add user", mUsername);
                        Toast.makeText(getApplicationContext(),
                                R.string.connect, Toast.LENGTH_LONG).show();
                        isConnected = true;
                    }
                }
            });
        }
    };

    private Emitter.Listener onDisconnect = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Log.i(TAG, "diconnected");
                    isConnected = false;
                    Toast.makeText(getApplicationContext(),
                            R.string.disconnect, Toast.LENGTH_LONG).show();
                }
            });
        }
    };

    private Emitter.Listener onConnectError = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Log.e(TAG, "Error connecting");
                    Toast.makeText(getApplicationContext(),
                            R.string.error_connect, Toast.LENGTH_LONG).show();
                }
            });
        }
    };

    private Emitter.Listener onNewMessage = new Emitter.Listener() {
        @Override
        public void call(final Object... args) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    JSONObject data = (JSONObject) args[0];
                    String username;
                    String message;
                    try {
                        username = data.getString("username");
                        message = data.getString("message");
                    } catch (JSONException e) {
                        Log.e(TAG, e.getMessage());
                        return;
                    }

//                    removeTyping(username);
//                    if (!username.equals(mUsername)) {
//                        addMessage(username, message);
//                    }
                }
            });
        }
    };

    private Emitter.Listener onUserJoined = new Emitter.Listener() {
        @Override
        public void call(final Object... args) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    JSONObject data = (JSONObject) args[0];
                    String username;
                    int numUsers;
                    try {
                        username = data.getString("username");
                        numUsers = data.getInt("numUsers");
                    } catch (JSONException e) {
                        Log.e(TAG, e.getMessage());
                        return;
                    }

//                    addLog(getResources().getString(R.string.message_user_joined, username));
//                    addParticipantsLog(numUsers);
                }
            });
        }
    };

//    private Emitter.Listener onUserLeft = new Emitter.Listener() {
//        @Override
//        public void call(final Object... args) {
//            runOnUiThread(new Runnable() {
//                @Override
//                public void run() {
//                    JSONObject data = (JSONObject) args[0];
//                    String username;
//                    int numUsers;
//                    try {
//                        username = data.getString("username");
//                        numUsers = data.getInt("numUsers");
//                    } catch (JSONException e) {
//                        Log.e(TAG, e.getMessage());
//                        return;
//                    }
//
//                    addLog(getResources().getString(R.string.message_user_left, username));
//                    addParticipantsLog(numUsers);
//                    removeTyping(username);
//                }
//            });
//        }
//    };
//
//    private Emitter.Listener onTyping = new Emitter.Listener() {
//        @Override
//        public void call(final Object... args) {
//            runOnUiThread(new Runnable() {
//                @Override
//                public void run() {
//                    JSONObject data = (JSONObject) args[0];
//                    String username;
//                    try {
//                        username = data.getString("username");
//                    } catch (JSONException e) {
//                        Log.e(TAG, e.getMessage());
//                        return;
//                    }
//                    addTyping(username);
//                }
//            });
//        }
//    };
//
//    private Emitter.Listener onStopTyping = new Emitter.Listener() {
//        @Override
//        public void call(final Object... args) {
//            runOnUiThread(new Runnable() {
//                @Override
//                public void run() {
//                    JSONObject data = (JSONObject) args[0];
//                    String username;
//                    try {
//                        username = data.getString("username");
//                    } catch (JSONException e) {
//                        Log.e(TAG, e.getMessage());
//                        return;
//                    }
//                    removeTyping(username);
//                }
//            });
//        }
//    };
}
